/*
 * Copyright (C) 2009 CodeWerkz
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */

package com.codewerkz.prompty;

import android.app.Activity;
import android.content.Intent;
import android.database.Cursor;
import android.os.Bundle;
import android.os.Handler;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.ImageButton;
import android.widget.TextView;

import com.codewerkz.util.Utils;

/**
 * SlideShow Activity.
 * 
 * @author ChaZ
 */
public class SlidesShow extends Activity implements OnClickListener{
	
	// Database Adapters and Cursor.
	private PresentationsDbAdapter mPresDbHelper;
	private SlidesDbAdapter mSlideDbHelper;
	private Cursor mSlide;
	private Cursor mPres;
	private int mDelayTime = 0;
	private boolean mDelayEnable = false;
	
	// Views etc.
	private TextView mTitleText;
    private TextView mBodyText;
	private Long mSlideRowId;
	private Long mPresRowId;
	private ImageButton mBtnPrev;
	private ImageButton mBtnNext;
	private TextView mProgressCount;
	
	// Result Codes.
	public static final int RESULT_NOSLIDES = 1;
	public static final int ACTIVITY_HELP_SLIDESHOW = 2;
	
	// Animations
	private static Animation sAnimationFadeIn;
	private static Animation sAnimationFadeOut;
	
	//private static final String TAG = "Prompty - SShow";

	/**
	 * Runs when the Activity is created.
	 * 
	 * @return void
	 */
    @Override
    protected void onCreate(Bundle savedInstanceState) {
    	super.onCreate(savedInstanceState);
    	
    	// Set up layout
    	setContentView(R.layout.slides_show);

    	// Set up views and onClick Listeners.
    	mBtnPrev = (ImageButton) findViewById(R.id.slideShow_btnPrev);
    	mBtnPrev.setOnClickListener(this);
      	mBtnNext = (ImageButton) findViewById(R.id.slideShow_btnNext);
      	mBtnNext.setOnClickListener(this);
      	
      	mTitleText = (TextView) findViewById(R.id.slideShow_slideTitle);
        mBodyText = (TextView) findViewById(R.id.slideShow_slideText);
        mProgressCount = (TextView) findViewById(R.id.slideShow_progressCount);
        
    	sAnimationFadeIn = AnimationUtils.loadAnimation(this, R.anim.fade_in);
    	sAnimationFadeOut  = AnimationUtils.loadAnimation(this, R.anim.fade_out);
        
    	// Open databases connections.
    	mPresDbHelper = new PresentationsDbAdapter(this);
    	mPresDbHelper.open();
    	
    	mSlideDbHelper = new SlidesDbAdapter(this);
    	mSlideDbHelper.open();
    	      
        // Get the extras from the Intent and set up us the variables.
        Bundle extras = getIntent().getExtras();
        
        mPresRowId = extras != null ? extras.getLong("presID")
				: null;
        mSlideRowId = extras != null ? extras.getLong("slideID") 
        							 : null;
      
        // If the (PresRowId Is EQUAL to 0) OR (The slide ID is EUQAL to 0) Then...
        if ( mPresRowId == 0 || mSlideRowId == 0 ) {
        	// We have none, set the result and return to the 
        	// the previous Activity (Most likely PresentationList)
            setResult(RESULT_NOSLIDES);
            finish();
        } else {
            // Otherwise refill the data.
            fillData();	
        }            
    }
    
	/**
	 * Sets up a timer that automatically advances to the next slide.
	 * 
	 * @param timeInSeconds Time in seconds till the next slide to appear.
	 * @return void
	 */
    private void timeToNextSlide(int timeInSeconds) {
    	// TODO: Improve exception handling (Detect if no next slide).
    	if(timeInSeconds != 0)
    	{
	        // New Handler to start the Menu-Activity
	        // and close this Splash-Screen after some seconds.
	        new Handler().postDelayed(new Runnable(){
	             @Override
	             public void run() {
	                 try
	                 {
	                	 nextSlide(true);
	                 }
	                 catch (Exception e)
	                 {
	                	 // Something has gone terribly wrong.
	                 }
	                  
	             } 
	        // We want it in seconds not milliseconds (x 1000!)
	        }, (timeInSeconds*1000));
    	}
    }
    
	/**
	 * Runs when an onClick listener is triggered.
	 * 
	 * @param v View Id of button clicked.
	 * @return void
	 */
	@Override
	public void onClick(View v) {
		// If the view is a mBtnNext...
		if(v == mBtnNext) {         
            nextSlide(true);
		}
		// If the view is a mBtnPrev...
		else if (v == mBtnPrev)
		{
            prevSlide(true);
		}
	}
	
    @Override
	/**
	 * Runs when the Activity is about to be destroyed for garbage collection.
	 * 
	 * @return void
	 */
    protected void onDestroy() {
    	super.onDestroy();
    	// Prevents database leak
    	mSlideDbHelper.close();
    	mPresDbHelper.close();
    }

	/**
	 * Fills the layout with the data.
	 * 
	 * @return void
	 */
	protected void fillData() {
		// Get all the slides for the particular presentation...
		mSlide = mSlideDbHelper.fetchAllSlides(mPresRowId);
		mPres = mPresDbHelper.fetchDelayInformation(mPresRowId);
		
		startManagingCursor(mPres);
		this.mDelayEnable = Utils.intToBool(mPres.getInt(mPres.getColumnIndexOrThrow(PresentationsDbAdapter.KEY_DELAYS)));
		
		// Manage the cursor...
        startManagingCursor(mSlide); 
        
        // Set up the count.
        int count = mSlide.getCount();
        
        // Cycle through all the records till we come to the slide we want
        // (If the user selected a particular slide rather than the presentation
        // which would send you to the first slide).
        for(int i = 0; i < count; i++) {
        	// If the slide isn't the one we want...
        	if (mSlide.getLong(mSlide.getColumnIndexOrThrow(SlidesDbAdapter.KEY_ROWID)) != mSlideRowId) {
        		// Move to the next one.
        		mSlide.moveToNext();
            }	
        }
        
        // Once we have it, set the layout to the relevant data sources.
        updateProgressCount(mSlide.getPosition(), count);
		mTitleText.setText(mSlide.getString(mSlide.getColumnIndexOrThrow(SlidesDbAdapter.KEY_STITLE)));
		mBodyText.setText(mSlide.getString(mSlide.getColumnIndexOrThrow(SlidesDbAdapter.KEY_STEXT)));
		if(mDelayEnable) {
			mDelayTime = mSlide.getInt(mSlide.getColumnIndexOrThrow(SlidesDbAdapter.KEY_DELAY));
			this.timeToNextSlide(mDelayTime);
		}
		
	}
	
	/**
	 * Sends the Activity to the next slide.
	 * 
	 * @param animation If true, will show the animation, otherwise it will not.
	 * @return void
	 */
	public void nextSlide(boolean animation) {
		// Manage the cursor.
		startManagingCursor(mSlide);
		// If we moved to the next slide (If not, there isn't another slide to move to)...
		if(mSlide.moveToNext()) {
			if(animation) { fadeOutTexts(); }
			// Set up the relevant views to the data.
			mTitleText.setText(mSlide.getString(mSlide.getColumnIndexOrThrow(SlidesDbAdapter.KEY_STITLE)));
			mBodyText.setText(mSlide.getString(mSlide.getColumnIndexOrThrow(SlidesDbAdapter.KEY_STEXT)));
			if(mDelayEnable) {
				mDelayTime = mSlide.getInt(mSlide.getColumnIndexOrThrow(SlidesDbAdapter.KEY_DELAY));
				this.timeToNextSlide(mDelayTime);
			}
			
			updateProgressCount(mSlide.getPosition(), mSlide.getCount());
			if(animation) { fadeInTexts(); }
		} else {
			// If there isn't a next slide, to prevent user noticing, move back but
			// not show animation to seem if not moved forward.
			prevSlide(false);
		}
	}
	
	/**
	 * Fades in the text views.
	 * 
	 * @return void
	 */
	private void fadeInTexts() {
		mTitleText.startAnimation(sAnimationFadeIn);
		mBodyText.startAnimation(sAnimationFadeIn);
	}
	
	/**
	 * Fades out the text views.
	 * 
	 * @return void
	 */
	private void fadeOutTexts() {
		mTitleText.startAnimation(sAnimationFadeOut);
		mBodyText.startAnimation(sAnimationFadeOut);		
	}
	
	/**
	 * Updates the progress count on the screen.
	 * 
	 * @param currentPos Current position.
	 * @param total Total number of slides.
	 * @return void
	 */
	private void updateProgressCount(int currentPos, int total) {
		mProgressCount.setText((currentPos+1) + "/" + total);
	}
	
	/**
	 * Sends the Activity to the previous slide.
	 * 
	 * @param animation If true it will show the animation, otherwise it will not.
	 * @return void
	 */
	public void prevSlide(boolean animation) {
		// Manage the cursor.
		startManagingCursor(mSlide);
		// If we moved to the previous slide (If not, there isn't another slide to move to)...
		if(mSlide.moveToPrevious()) {
			if(animation) { fadeOutTexts(); }
			// Set up the relevant views to the data.
			mTitleText.setText(mSlide.getString(mSlide.getColumnIndexOrThrow(SlidesDbAdapter.KEY_STITLE)));
			mBodyText.setText(mSlide.getString(mSlide.getColumnIndexOrThrow(SlidesDbAdapter.KEY_STEXT)));
			updateProgressCount(mSlide.getPosition(), mSlide.getCount());
			if(animation) { fadeInTexts(); }
		} else {
			// If there isn't a previous slide, to prevent user noticing, move next but
			// not show animation to seem if not moved forward.
			nextSlide(false);
		}
	}	
	
	/**
	 * Runs when the Menu button is pressed.
	 * 
	 * @param menu Resource Id of the menu.
	 * @return boolean
	 */
    public boolean onCreateOptionsMenu(Menu menu) {
    	// Create an inflation object and inflate the menu layout.
    	MenuInflater inflater = getMenuInflater();
    	inflater.inflate(R.menu.slideshow_options, menu);
    	return true;
    }
    
	/**
	 * Runs when the user selects a button from the Menu.
	 * 
	 * @param item Item Id of the MenuItem.
	 * @return boolean
	 */
    public boolean onOptionsItemSelected(MenuItem item) {
    	// Switch all the button.
        switch (item.getItemId()) {
        	case R.id.slidesShow_help:
        		showHelp();
        		return true;
        	}
        return false;
    }
    
	/**
	 * Shows the Help screen.
	 * 
	 * @return void
	 */
    private void showHelp() {
    	Intent i = new Intent (this, Help.class);
    	i.putExtra("helpPage", 3);
    	this.startActivityForResult(i, ACTIVITY_HELP_SLIDESHOW);
    }
}
